package com.bridgeQQ.client.control
{
	import com.bridgeQQ.client.constant.CommandConst;
	import com.bridgeQQ.client.constant.MsgCont;
	import com.bridgeQQ.client.core.client.IConnectionClient;
	import com.bridgeQQ.client.core.message.IMessageDisplay;
	import com.bridgeQQ.client.core.message.IMessageRelation;
	import com.bridgeQQ.client.events.CommandEvent;
	import com.bridgeQQ.client.events.SendEvent;
	import com.bridgeQQ.client.model.BridgeModel;
	import com.bridgeQQ.client.util.ModelUtil;
	import com.bridgeQQ.client.view.window.FriendInfoWindow;
	import com.bridgeQQ.client.view.window.FriendMsgWindow;
	import com.bridgeQQ.client.view.window.MsgDisplayWindow;
	import com.bridgeQQ.client.view.window.message.BridgeChatWindow;
	import com.bridgeQQ.client.view.window.message.NormalChatWindow;
	import com.bridgeQQ.client.vo.User;
	
	import flash.desktop.DockIcon;
	import flash.desktop.NativeApplication;
	import flash.desktop.SystemTrayIcon;
	import flash.display.NativeMenu;
	import flash.display.NativeMenuItem;
	import flash.display.Screen;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.ScreenMouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	
	import mx.core.Application;
	import mx.core.Window;
	import mx.messaging.messages.IMessage;
	
	public class MessageManager extends EventDispatcher
	{
		
		public var bridgeEnable:Boolean = true;
		
		[Embed(source="assets/logo.gif")]
		private var logo:Class;
		
		[Embed(source="assets/empty.gif")]
		private var empty:Class;
		
		private var opendMsgQuue:Array = [];
		
		private var messageQueue:Array = [];
		
		private var animateTimer:Timer;
		
		/**
		 *topic和window的映射，一个topic对应一个window 
		 */		
		private var topicWindows:Array = [];
		
		public function MessageManager()
		{
			initSystemTray();
			setupMsgClinet("peer");
			setupMsgClinet("server");
		}
		
		/**
		 * 收到msg,如果该msg的窗口已经打开，则把该信息添加到窗口，并highlight;
		 * 否则闪烁system tray 
		 * @param msg： 新收到的信息
		 * 
		 */		
		public function receiveMsg(msg:IMessage):void
		{
			var topic:String = getMsgTopic(msg);
			var window:IMessageDisplay = topicWindows[topic];
			if(window != null && !window.hide)
			{
				window.receiveMsg(msg);
				return;
			}
			messageQueue.push(msg);
			checkSystemTray();
		}
		
		/**
		 * 忽略所有messageQueue中的system tray提示,
		 * 把这些信息移到opendMsgQuue之中
		 */		
		public function ignoreAllMsgSystemTray():void
		{
			
		}
		
		public function openMsgWindow(topic:String, type:String, relations:Array):IMessageDisplay
		{
			var window:IMessageDisplay = topicWindows[topic];
			var newCreate:Boolean;
			if(window == null)
			{
				newCreate = true;
				window = createMsgDispayWindow(topic, type);
				if(window is IMessageRelation && relations)
				{
					var length:int = relations.length;	
					for(var i:int = 0; i < length; i++)
					{
						IMessageRelation(window).addRelation(relations[i]);
					}				
				}
			}
			window.openDisplay();
			if(newCreate)
				location(window as Window);
		   return window;
		}
		
		/**
		 * Send peer msg. when the destionations have had it, the msg is sent to 
		 * user's self. 
		 * @param msg
		 * @param destinations
		 * @param connectionType: can be "peer" or "server", if the connection type is not specified,
		 * it will be made acoording to destination 's  status
		 */		
		public function sendMsg(msg:IMessage, destinations:Array, connectionType:String = null):Array
		{
			var ids:Array = [];
			var client:IConnectionClient;
			for(var i:int = destinations.length - 1; i >= 0; i--)
			{
				var friend:String = destinations[i];
				var user:User = ModelUtil.getFriend(BridgeModel.instance.possess, "email", friend);
				if(user == null)
				{
					user = ModelUtil.getUserFromPool(friend);
				}
				var peerID:String = user ? user.peerID : null;
				peerID = (peerID != null && peerID.length >= 64) && connectionType != "server" ? peerID : friend;
				if(connectionType == "peer" && (peerID == null || peerID.length < 64))
				{
					continue;
				}
				client = peerID.length < 64 ? setupMsgClinet("server") : setupMsgClinet("peer");
				ids.push(client.send(peerID, "onReceiveConnectionMsg", msg));	
			}
			return ids;
		}
		
		private function setupMsgClinet(type:String):IConnectionClient
		{
			var client:IConnectionClient;
			if(type == "peer")
			{
				client = ApplicationController.controller.getSubController("peerClient");			
			}
			else if(type == "server")
			{
				client = ApplicationController.controller.getSubController("serverClient");			
			}
			if(!client.willTrigger(SendEvent.SUCCESS))
			{
				client.registerHandler("onReceiveConnectionMsg", onReceiveConnectionMsg);
				client.addEventListener(SendEvent.SUCCESS, onPeerSendResult);
				client.addEventListener(SendEvent.ERROR, onPeerSendResult);
				client.addEventListener(SendEvent.TIME_OUT, onPeerSendResult);
			}
			return client;
		}
		
		private function onPeerSendResult(event:SendEvent):void
		{
			event.stopPropagation();
			this.dispatchEvent(SendEvent(event.clone()));
		}
		
		public function onReceiveConnectionMsg(farID:String, msg:IMessage):void
		{
			this.receiveMsg(msg);	
		}
		
		private function getMsgTopic(msg:IMessage):String
		{
			var type:String = msg.headers.type;
			if(type == MsgCont.MSG_TYPE_NORMAL)
			{
				return msg.headers.from;
			}
			if(type == MsgCont.MSG_TYPE_BRIDGE)
			{
				return msg.headers.topic;
			}
			return msg.headers.type + msg.headers.from as String;
		}
		
		/**
		 * 从mesageQueue中打开一条信息,如果该信息已经有window了，则打开window;
		 * 否则创建window
		 */		
		private function openMessage():void
		{
			var msg:IMessage = messageQueue.pop();
			opendMsgQuue.push(msg);
			var topic:String = getMsgTopic(msg);
			var window:IMessageDisplay = topicWindows[topic];
			var newCreate:Boolean;
			if(window == null)
			{
				newCreate = true;
				var type:String =  msg.headers.type;
				window = createMsgDispayWindow(topic, type);
				if(type == MsgCont.MSG_TYPE_NORMAL)
				{
					IMessageRelation(window).addRelation(msg.headers.from);
				}
			}
			window.receiveMsg(msg, false);
			window.openDisplay();	
			if(newCreate)
				location(window as Window);
		}
			
		private function createMsgDispayWindow(topic:String, msgType:String):IMessageDisplay
		{
			var window:IMessageDisplay;
			switch(msgType)
			{
				case MsgCont.MSG_TYPE_REQUEST_FRIEDD:
				    window = new FriendMsgWindow();
				    break
				case MsgCont.MSG_TYPE_REPLY_ADD_FRIEND:
				    window = new FriendInfoWindow();
				    break;
				case MsgCont.MSG_TYPE_NORMAL:
				    window = new NormalChatWindow();			    
				    break;
				case MsgCont.MSG_TYPE_BRIDGE:
				    window = new BridgeChatWindow();
				    break;
				default:
				   window = new MsgDisplayWindow();
			}
			window.topic = topic;
			topicWindows[topic] = window;
			var closable:Boolean;
			if(msgType == MsgCont.MSG_TYPE_REQUEST_FRIEDD || msgType == MsgCont.MSG_TYPE_REPLY_ADD_FRIEND)
			{
				closable = true;
			}	
			window.closable = closable;
			window.addEventListener("close", onWindowClose);
			return window;
		}
		
		private function location(window:Window):void
		{
			if(!window)
			{
				return;
			}
			var screen:Rectangle = Screen.mainScreen.bounds;
			window.move((screen.width - window.width) / 2, (screen.height - window.height) / 2);
		}
		
		private function checkSystemTray():void
		{
		    if(animateTimer != null && animateTimer.running)
		    {
		    	return;
		    }
		    if(messageQueue.length <= 0)
		    {
		    	return;
		    }
		    if(animateTimer == null)
		    {
		    	animateTimer = new Timer(200);
		    	animateTimer.addEventListener(TimerEvent.TIMER, onTimerAnimate);
		    }
		    animateTimer.reset();
		    animateTimer.start();
		}
		
		private function onTimerAnimate(event:TimerEvent):void
		{
			if(messageQueue.length <= 0)
		    {
		    	animateTimer.stop();
		    	NativeApplication.nativeApplication.icon.bitmaps = getCurrentSystemTrayIcons();
		    	return;
		    }
			var icon:Object = NativeApplication.nativeApplication.icon;
			icon.bitmaps = animateTimer.currentCount % 2 == 0 ? getCurrentSystemTrayIcons() : [new empty()];
		}
		
		protected function getCurrentSystemTrayIcons():Array
		{
			return [new logo()];
		}
		
		private function initSystemTray():void
		{
			if(NativeApplication.supportsSystemTrayIcon)
			{
				var tray:SystemTrayIcon = NativeApplication.nativeApplication.icon as SystemTrayIcon;
           		tray.bitmaps = getCurrentSystemTrayIcons();
           		tray.addEventListener(ScreenMouseEvent.MOUSE_DOWN, onTrayDown);
           		//NativeApplication.nativeApplication.autoExit = false;
           		var iconMenu:NativeMenu = new NativeMenu();
	            var exitCommand:NativeMenuItem = iconMenu.addItem(new NativeMenuItem("退出"));
                exitCommand.addEventListener(Event.SELECT, function(event:Event):void 
                {   
                	if(!BridgeModel.instance.user)
                	{
                		exit();
                		return;
                	} 	
                    Application.application.dispatchEvent(new CommandEvent(CommandEvent.COMMAND_ACTIVATE,
                        CommandConst.LOGOUT, {}));
                });
                
                function exit():void
                {
                	NativeApplication.nativeApplication.icon.bitmaps = [];
                    NativeApplication.nativeApplication.exit();
                }
                
	            tray.menu = iconMenu;
			}
			else if(NativeApplication.supportsDockIcon)
			{
				 var dock:DockIcon = NativeApplication.nativeApplication.icon as DockIcon;
			}
		}
		
		private function onWindowClose(event:Event):void
		{
			var target:IMessageDisplay = event.currentTarget as IMessageDisplay;
			var topic:String = target.topic;
			delete topicWindows[topic];
		}
		
		private function onTrayDown(event:Event):void
		{
			if(messageQueue.length <= 0)
			{
				if(Application.application.visible == false)
				{
					Application.application.visible = true;
					Application.application.nativeWindow.activate();
				}
				return;
			}
			openMessage();
		}

	}
}